package com.hisense.ovcloud.ps.routers;

import com.hisense.ovcloud.commons.configs.base.BaseResponse;
import com.hisense.ovcloud.commons.configs.validator.BaseRouterConfiguration;
import com.hisense.ovcloud.ps.dto.common.WgpsStatus;
import com.hisense.ovcloud.ps.dto.req.*;
import com.hisense.ovcloud.ps.dto.resp.OldVertifyResp;
import com.hisense.ovcloud.ps.service.PsService;
import com.hisense.ovcloud.ps.service.TokenServiceZip;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springdoc.core.annotations.RouterOperation;
import org.springdoc.core.annotations.RouterOperations;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.SynchronousSink;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.function.BiConsumer;

import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration
public class RoutingConfiguration extends BaseRouterConfiguration {

    private final TokenServiceZip tokenServiceZip;


    private final PsService psService;

    private final Validator certifyReqValidator;

    private final Validator verifyReqValidator;

    private final Validator wifiOnlineReqValidator;

    private final Validator getWifiStatReqValidator;

    private final Validator getWifiListStatReqValidator;

    private BiConsumer<CertifyReq, SynchronousSink<CertifyReq>> certifyReqValidatorHandler;

    private BiConsumer<VerifyReq, SynchronousSink<VerifyReq>> verifyReqValidatorHandler;

    private BiConsumer<WifiOnlineReq, SynchronousSink<WifiOnlineReq>> wifiOnlineReqValidatorHandler;

    private BiConsumer<GetWifiStatReq, SynchronousSink<GetWifiStatReq>> getWifiStatReqValidatorHandler;

    private BiConsumer<GetWifiListStatReq, SynchronousSink<GetWifiListStatReq>> getWifiListStatReqValidatorHandler;

    @PostConstruct
    public void init() {
        certifyReqValidatorHandler = (body, sink) -> validate(sink, certifyReqValidator, body, CertifyReq.class);
        verifyReqValidatorHandler = (body, sink) -> validate(sink, verifyReqValidator, body, VerifyReq.class);
        wifiOnlineReqValidatorHandler = (body, sink) -> validate(sink, wifiOnlineReqValidator, body, WifiOnlineReq.class);
        getWifiStatReqValidatorHandler = (body, sink) -> validate(sink, getWifiStatReqValidator, body, GetWifiStatReq.class);
        getWifiListStatReqValidatorHandler = (body, sink) -> validate(sink, getWifiListStatReqValidator, body, GetWifiListStatReq.class);
    }


    public RoutingConfiguration(TokenServiceZip tokenServiceZip, PsService psService, @Qualifier("certifyReqValidator") Validator certifyReqValidator, @Qualifier("verifyReqValidator") Validator verifyReqValidator, @Qualifier("wifiOnlineReqValidator") Validator wifiOnlineReqValidator, @Qualifier("getWifiStatReqValidator") Validator getWifiStatReqValidator, @Qualifier("getWifiListStatReqValidator") Validator getWifiListStatReqValidator) {
        this.tokenServiceZip = tokenServiceZip;
        this.psService = psService;
        this.certifyReqValidator = certifyReqValidator;
        this.verifyReqValidator = verifyReqValidator;
        this.wifiOnlineReqValidator = wifiOnlineReqValidator;
        this.getWifiStatReqValidator = getWifiStatReqValidator;
        this.getWifiListStatReqValidator = getWifiListStatReqValidator;
    }

    @Bean
    @RouterOperations({
            @RouterOperation(
                    path = "/ac-julink-ps/certify",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "certify",
                            operationId = "certify",
                            description = "certify",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "CertifyReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = CertifyReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-julink-ps/verify",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "verify",
                            operationId = "verify",
                            description = "verify",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "VerifyReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = VerifyReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-julink-ps/wifiOnline",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "wifiOnline",
                            operationId = "wifiOnline",
                            description = "wifiOnline",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "WifiOnlineReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = WifiOnlineReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-julink-ps/getWifiListStats",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "getWifiListStats",
                            operationId = "getWifiListStats",
                            description = "getWifiListStats",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetWifiListStatReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetWifiListStatReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-julink-ps/getWifiStats",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "getWifiStats",
                            operationId = "getWifiStats",
                            description = "getWifiStats",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetWifiStatReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetWifiStatReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            )
    })
    public RouterFunction<ServerResponse> authRoutes() {
        return RouterFunctions.nest(path("/ac-julink-ps"),
                route()
                        .POST("/certify", req -> ServerResponse.ok().body(tokenServiceZip.certify(req.bodyToMono(CertifyReq.class).handle(certifyReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/verify", req -> ServerResponse.ok().body(tokenServiceZip.verify(req.bodyToMono(VerifyReq.class).handle(verifyReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/wifiOnline", req -> ServerResponse.ok().body(psService.wifiOnline(req.bodyToMono(WifiOnlineReq.class).handle(wifiOnlineReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/getWifiStats", req -> ServerResponse.ok().body(psService.getWifiStats(req.bodyToMono(GetWifiStatReq.class).handle(getWifiStatReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/getWifiListStats", req -> ServerResponse.ok().body(psService.getWifiListStats(req.bodyToMono(GetWifiListStatReq.class).handle(getWifiListStatReqValidatorHandler)),
                                BaseResponse.class))
                        .build());
    }

    @Bean
    @RouterOperations({
            @RouterOperation(
                    path = "/zc-julink-ps/v1/getWifiListStats",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "getWifiListStats",
                            operationId = "getWifiListStats",
                            description = "getWifiListStats",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetWifiListStatReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetWifiListStatReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = List.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/zc-julink-ps/v1/getWifiStats",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            summary = "getWifiStats",
                            operationId = "getWifiStats",
                            description = "getWifiStats",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetWifiStatReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetWifiStatReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WgpsStatus.class)))
                            }
                    )
            )
    })
    public RouterFunction<ServerResponse> himitRoutes() {
        return RouterFunctions.nest(path("/zc-julink-ps/v1"),
                route()
                        .POST("/getWifiStats", req -> ServerResponse.ok().body(psService.getWifiStatsBase(req.bodyToMono(GetWifiStatReq.class).handle(getWifiStatReqValidatorHandler)),
                                WgpsStatus.class))
                        .POST("/getWifiListStats", req -> ServerResponse.ok().body(psService.getWifiListStatsBase(req.bodyToMono(GetWifiListStatReq.class).handle(getWifiListStatReqValidatorHandler)),
                                List.class))
                        .build());
    }

    @Bean
    public RouterFunction<ServerResponse> warehouseHimitRoutes() {
        return RouterFunctions.nest(path("/zc-julink-auth/v1"),
                route()
                        .POST("/vertify", req -> ServerResponse.ok().body(tokenServiceZip.vertify(req.bodyToMono(VerifyReq.class).handle(verifyReqValidatorHandler)),
                                OldVertifyResp.class))
                        .build());
    }

}

